#include "os_sal.h"


/* os sem 信号量 */


/* export func */


#if (CONFIG_OS_ENABLE == 1)

#if defined(CONFIG_OS_TYPE_FREERTOS)

#include "FreeRTOS.h"
#include "semphr.h"

extern 


/**
 * @brief OS创建二值信号量
 * 
 * @return os_sem_handle_t 二值信号量句柄
 */
os_sem_handle_t os_sem_binary_create(void)
{
	os_sem_handle_t sem;

	sem = xSemaphoreCreateBinary();
	
	return sem;
}

/**
 * @brief OS创建计数型信号量
 * 
 * @param def 初始值
 * @param max 最大值
 * @return os_sem_handle_t 计数型信号量句柄
 */
os_sem_handle_t os_sem_count_create(uint32_t def, uint32_t max)
{
	os_sem_handle_t sem;

	sem = xSemaphoreCreateCounting(max, def);

	return sem;
}

/**
 * @brief OS获取计数型信号量值
 * 
 * @param sem 信号量句柄
 * @param cnt 信号量值
 * @return os_status_t 
 */
os_status_t os_sem_count_get_count(os_sem_handle_t sem, uint32_t *cnt)
{
	if (sem == NULL) return OS_STA_ERROR;

	*cnt = uxSemaphoreGetCount(sem);
	return OS_STA_SUCCESS;
}

/**
 * @brief OS删除信号量
 * 
 * @param sem 信号量句柄
 * @return os_status_t 
 */
os_status_t os_sem_delete(os_sem_handle_t sem)
{
	if (sem == NULL) return OS_STA_ERROR;

	vSemaphoreDelete(sem);
	return OS_STA_SUCCESS;
}

/**
 * @brief OS获取信号量(不可在中断中调用)
 * 
 * @param sem 信号量句柄
 * @param waittime 等待时间(OS_WAIT_MAX不超时等待)
 * @return os_status_t 
 */
os_status_t os_sem_take(os_sem_handle_t sem, uint32_t waittime)
{
	os_status_t os_sta;
	BaseType_t err;

	if (sem == NULL) return OS_STA_ERROR;
	err = xSemaphoreTake((SemaphoreHandle_t)sem, waittime);
	if (err == pdPASS) os_sta = OS_STA_SUCCESS;
	else os_sta = OS_STA_ERROR;

	return os_sta;
}

//
//sem:
//return:
/**
 * @brief OS释放信号量
 * 
 * @param sem 信号量句柄
 * @return os_status_t 
 */
os_status_t os_sem_release(os_sem_handle_t sem)
{
	os_status_t os_sta;
	BaseType_t err;
	portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE;
	uint8_t isrcount;

	if (sem == NULL) return OS_STA_ERROR; 
	isrcount = ulPortGetIPSR();
	if (isrcount > 0)
	{
		err = xSemaphoreGiveFromISR((SemaphoreHandle_t)sem, &pxHigherPriorityTaskWoken);
		if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount))
		{
			portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
		}
	}
	else
	{
		err = xSemaphoreGive((SemaphoreHandle_t)sem);
	}

	if (err == pdPASS) os_sta = OS_STA_SUCCESS;
	else os_sta = OS_STA_ERROR;
	
	return os_sta;
}


#else
    #error "CONFIG_OS_TYPE not support!"
#endif // CONFIG_OS_TYPE

#endif // CONFIG_OS_ENABLE


